package com.ajavaer.framework.core.orm;

import com.ajavaer.framework.common.tools.ObjectTools;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

@SuppressWarnings("unchecked")
public abstract class BaseRunSQL {
    protected EntityManagerFactory emf;

    public abstract void setEntityManagerFactory(EntityManagerFactory emf);

    /**
     * 开始事务
     */
    public EntityManager txBegin() {
        EntityManager newEm = this.emf.createEntityManager();
        EntityTransaction newTx = newEm.getTransaction();
        newTx.begin();
        return newEm;
    }

    /**
     * 提交事务
     */
    public void txCommit(EntityManager entityManager) {
        if (entityManager != null) {
            entityManager.getTransaction().commit();
            entityManager.close();
        }
    }

    /**
     * 回滚事务
     */
    public void txRollBack(EntityManager entityManager) {
        if (entityManager != null) {
            entityManager.getTransaction().rollback();
            entityManager.close();
        }
    }

    protected Query createQuery(EntityManager entityManager, String sql, Object... params) {
        Query query = entityManager.createNativeQuery(sql);
        if (ObjectTools.isNotBlank(params)) {
            if (params.length == 1 && params[0] instanceof Map) {
                return createQuery(entityManager, sql, (Map<String, Object>) params[0]);
            } else {
                for (int i = 0; i < params.length; i++) {
                    query.setParameter(i + 1, params[i]);
                }
            }
        }
        return query;
    }

    protected Query createQuery(EntityManager entityManager, String sql, Map<String, Object> params) {
        Query query = entityManager.createNativeQuery(sql);
        if (ObjectTools.isNotBlank(params)) {
            for (String o : params.keySet()) {
                query.setParameter(o, params.get(o));
            }
        }
        return query;
    }

    /**
     * 执行sql语句，指定返回类型
     *
     * @param sql
     * @param clazz
     * @return
     */
    public <T> List<T> executeSQL(String sql, Class<T> clazz) {
        return executeSQL(sql, null, clazz);
    }

    /**
     * 执行sql语句，指定返回类型
     *
     * @param sql
     * @param clazz
     * @return
     */
    public <T> List<T> executeSQL(String sql, Map<String, Object> parameters,
                                  Class<T> clazz) {
        EntityManager newEm = this.emf.createEntityManager();
        try {
            Query query = newEm.createNativeQuery(sql, clazz);
            if (parameters != null) {
                for (Entry<String, Object> p : parameters.entrySet()) {
                    query.setParameter(p.getKey(), p.getValue());
                }
            }
            return query.getResultList();
        } finally {
            newEm.close();
        }

    }

    /**
     * 执行sql语句
     *
     * @param sql
     * @return
     */
    public List<?> executeSQL(String sql) {
        return executeSQL(sql, new HashMap<>());
    }

    /**
     * 执行查询,占位符(:name)
     *
     * @param sql
     * @param parameters
     * @return
     */
    public List<?> executeSQL(String sql, Map<String, Object> parameters) {
        EntityManager newEm = this.emf.createEntityManager();
        try {
            Query query = newEm.createNativeQuery(sql);
            if (parameters != null && parameters.size() > 0) {
                for (Entry<String, Object> p : parameters.entrySet()) {
                    query.setParameter(p.getKey(), p.getValue());
                }
            }
            return executeQuery(query);
        } finally {
            newEm.close();
        }
    }

    /**
     * 执行复合查询
     *
     * @param query
     * @return
     */
    public List<?> executeSQL(CriteriaQuery<?> query) {
        EntityManager newEm = this.emf.createEntityManager();
        try {
            return executeQuery(newEm.createQuery(query));
        } finally {
            newEm.close();
        }
    }

    public Object executeSQLSingleResult(String sql) {
        EntityManager newEm = this.emf.createEntityManager();
        try {
            return newEm.createNativeQuery(sql).getSingleResult();
        } finally {
            newEm.close();
        }
    }


    /**
     * 执行查询
     *
     * @param query
     * @return
     */
    public List<?> executeQuery(Query query) {
        return query.getResultList();
    }

    /**
     * Return an instance of CriteriaBuilder for the creation of CriteriaQuery
     * objects.
     *
     * @return
     */
    private CriteriaBuilder getCriteriaBuilder() {
        return this.emf.createEntityManager().getCriteriaBuilder();
    }

    /**
     * 执行sql，带事务
     *
     * @param sql
     * @return
     */
    public int executeUpdate(String sql, Object... params) {
        EntityManager newEm = this.emf.createEntityManager();
        try {
            Query query = createQuery(newEm, sql, params);
            EntityTransaction newTx = newEm.getTransaction();
            newTx.begin();
            int count = query.executeUpdate();
            newTx.commit();
            return count;
        } finally {
            newEm.close();
        }
    }

    /**
     * 执行sql，不带事务,注意一定要提交或回滚事务,不然会造成连接泄漏
     *
     * @param sql
     * @return
     */
    public int executeUpdateWithoutTx(EntityManager entityManager, String sql, Object... params) {
        Query query = createQuery(entityManager, sql, params);
        return query.executeUpdate();
    }
}
